feat: Add Hip 1261 Implementation#2019
Conversation
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
|
Hi, this is WorkflowBot.
|
|
I have a version of execute where the tests do pass. I am happy to share this version if needed. :) |
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
manishdait
left a comment
There was a problem hiding this comment.
Great work @aceppaluni, left a few suggestions.
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughImplements HIP-1261 fee estimation support by introducing frozen dataclasses for fee models (FeeEstimate, FeeExtra, NetworkFee, FeeEstimateResponse), an enum for estimation modes (FeeEstimateMode), and a query builder class (FeeEstimateQuery) that communicates with the Mirror Node API. Adds a convenience method to Transaction and updates TransferTransaction to accept string-formatted account IDs. Changes
Sequence DiagramsequenceDiagram
participant Client as Client Code
participant Query as FeeEstimateQuery
participant TX as Transaction
participant Serializer as Protobuf Serializer
participant MirrorNode as Mirror Node API
participant Parser as Response Parser
Client->>Query: set_transaction(tx)
Client->>Query: set_mode(mode)
Client->>Query: execute(client)
Query->>Query: Validate transaction set
Query->>Query: Select mode (default: STATE)
Query->>TX: Serialize to protobuf bytes
Query->>Serializer: to_bytes() / freeze_with() / freeze()
Serializer-->>Query: protobuf bytes
Query->>MirrorNode: POST /api/v1/network/fees<br/>Content-Type: application/protobuf
alt Retry Transient Error
MirrorNode-->>Query: Exception (UNAVAILABLE/DEADLINE_EXCEEDED)
Query->>Query: Exponential backoff retry
Query->>MirrorNode: Retry POST
end
alt HTTP 400
MirrorNode-->>Query: 400 Bad Request
Query-->>Client: ValueError("Invalid argument")
else HTTP 200
MirrorNode-->>Query: 200 OK (JSON)
Query->>Parser: Parse fee response JSON
Parser->>Parser: Calculate:<br/>node_total = base + extras<br/>service_total = base + extras<br/>network_total = node_total × multiplier<br/>total = node_total + service_total + network_total
Parser-->>Query: FeeEstimateResponse
end
Query-->>Client: FeeEstimateResponse
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📋 Issue PlannerBuilt with CodeRabbit's Coding Plans for faster development and fewer bugs. View plan used: ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
♻️ Duplicate comments (1)
src/hiero_sdk_python/query/fee_estimate_query.py (1)
48-60:⚠️ Potential issue | 🔴 CriticalUse the actual
ClientREST/retry API here.The concrete client exposes
network.get_mirror_rest_url()andmax_attempts, notmirror_network/max_retries. With a realClient, Line 48 raisesAttributeError, and the retry loop ignores the caller’s configured attempt budget.🐛 Suggested fix
- url = f"{client.mirror_network}/api/v1/network/fees?mode={mode.value}" + url = f"{client.network.get_mirror_rest_url()}/network/fees?mode={mode.value}" @@ - max_retries = getattr(client, "max_retries", 3) + max_retries = client.max_attemptsVerify against the actual client/network definitions:
#!/bin/bash set -euo pipefail rg -n '\bmirror_network\b|\bmax_retries\b|\bmax_attempts\b|get_mirror_rest_url' \ src/hiero_sdk_python/query/fee_estimate_query.py \ src/hiero_sdk_python/client/client.py \ src/hiero_sdk_python/client/network.py
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 8f0c538d-669e-4bc6-a84f-971b8df7fb8e
📒 Files selected for processing (10)
CHANGELOG.mdsrc/hiero_sdk_python/fees/fee_estimate.pysrc/hiero_sdk_python/fees/fee_estimate_mode.pysrc/hiero_sdk_python/fees/fee_estimate_response.pysrc/hiero_sdk_python/fees/fee_extra.pysrc/hiero_sdk_python/fees/network_fee.pysrc/hiero_sdk_python/query/fee_estimate_query.pysrc/hiero_sdk_python/transaction/transaction.pysrc/hiero_sdk_python/transaction/transfer_transaction.pytests/unit/test_fee_estimate_query.py
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
|
Hello, this is the OfficeHourBot. This is a reminder that the Hiero Python SDK Office Hours are scheduled in approximately 4 hours (14:00 UTC). This session provides an opportunity to ask questions regarding this Pull Request. Details:
Disclaimer: This is an automated reminder. Please verify the schedule here for any changes. From, |
|
Still working, thank you. |
|
Hi @aceppaluni, This pull request has had no commit activity for 10 days. Are you still working on it?
If you're no longer working on this, please comment Reach out on discord or join our office hours if you need assistance. From the Python SDK Team |
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 72 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Actionable comments posted: 8
♻️ Duplicate comments (2)
src/hiero_sdk_python/fees/fee_estimate_response.py (1)
14-14: 🧹 Nitpick | 🔵 TrivialConsider making
totala computed property to enforce the fee formula invariant.Storing
totalas a separate field risks drift fromnode_fee/network_fee/service_feesubtotals. The PR objective specifies a precise formula:total = node_fee + network_fee + service_fee. A computed property would guarantee this invariant.Note: Since this is a frozen dataclass, you'd need to use
__post_init__validation or convert to a computed property with@property.src/hiero_sdk_python/query/fee_estimate_query.py (1)
98-100:⚠️ Potential issue | 🟠 MajorHardcoded
max_retries = 2ignores the configurable_max_attempts.The class has
self._max_attempts = 10(line 21) with a setter, but the retry loop uses a hardcodedmax_retries = 2. The configuration is effectively ignored.🐛 Proposed fix
- max_retries = 2 - - for attempt in range(max_retries): + for attempt in range(self._max_attempts): try: response = requests.post(Also update line 117:
- if attempt == max_retries - 1: + if attempt == self._max_attempts - 1:
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 503a1344-e43d-4626-b178-6c0427ee3e27
📒 Files selected for processing (3)
src/hiero_sdk_python/fees/fee_estimate_response.pysrc/hiero_sdk_python/fees/fee_extra.pysrc/hiero_sdk_python/query/fee_estimate_query.py
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
exploreriii
left a comment
There was a problem hiding this comment.
Hi @aceppaluni please delete your changelog and fix codacy issues that are relevant :)
There was a problem hiding this comment.
Actionable comments posted: 10
♻️ Duplicate comments (4)
src/hiero_sdk_python/query/fee_estimate_query.py (4)
27-27:⚠️ Potential issue | 🟠 Major
FeeEstimateQuerystill bypasses theQuerybase class.Per coding guidelines for
src/hiero_sdk_python/query/**/*.py, newly added query subclasses must extendQuerydirectly and delegate execution lifecycle (retries, backoff,_before_execute, node selection) to_Executable; subclasses must not implement custom retry logic or manage deadlines manually. This class is a standalone builder with its own HTTP retry loop, no inheritance fromQuery, and none of the required abstract methods (_make_request,_get_query_response,_get_method).While HIP-1261 targets the Mirror Node REST API rather than gRPC, it still needs to integrate with the existing query architecture (e.g., via a Mirror-style query base or a thin adapter that preserves the base lifecycle) so retries/backoff/error propagation remain consistent with the rest of the SDK.
As per coding guidelines: "Ensure they extend
Querydirectly; Verify required abstract methods are implemented; ... Subclasses MUST NOT: Override retry logic ... Manage gRPC deadlines manually".
62-62:⚠️ Potential issue | 🟠 Major
_max_backoff = 0still disables backoff.With
self._max_backoff = 0,_backoff()computesdelay = min(0.5 * 2**attempt, 0) = 0, so retries fire immediately. This defeats the retry policy required by HIP-1261 forUNAVAILABLE/DEADLINE_EXCEEDEDand can hammer the Mirror Node.🐛 Proposed fix
- self._max_attempts = 10 - self._max_backoff = 0 + self._max_attempts = 10 + self._max_backoff = 8 # seconds
147-164:⚠️ Potential issue | 🟠 MajorSilent
b""fallback still produces invalid requests.If every serialization path fails, the function returns
b""andexecute()posts an empty body, which the Mirror Node will either reject opaquely or produce a meaningless estimate. Raise instead so the caller sees a clear error.🐛 Proposed fix
try: body = transaction.build_transaction_body() return body.SerializeToString() if body else b"" except Exception as exc: # pylint: disable=broad-exception-caught - logger.warning("All serialization methods failed: %s", exc) - return b"" + raise ValueError( + f"Failed to serialize transaction for fee estimation: {exc}" + ) from exc
196-228:⚠️ Potential issue | 🟠 MajorChunked transactions are not aggregated;
responsecan beNone.Two concerns on the execute path:
- HIP-1261 requires
FileAppendTransactionandTopicMessageSubmitTransactionfee estimates to be computed per chunk and summed into a single response. The current implementation serializes the transaction once and posts a single request, so chunk fees are never aggregated. The multi-chunk test (test_topic_message_multiple_chunks) only assertsresult is not None, which hides this gap._post_with_retrycan returnNone(line 194) when its loop exits without success;response.json()on line 208 would then raiseAttributeError. Either make_post_with_retryalways raise on exhaustion or guard here.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 1697abed-2387-4266-9118-42e55e271b54
📒 Files selected for processing (3)
src/hiero_sdk_python/query/fee_estimate_query.pytests/unit/fee_estimate_query_test.pytests/unit/transaction_test.py
|
@aceppaluni to help speed up the review, could you please resolve any conversations and also fix the linting? we have added a pre commit hook you'll need to enable |
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
Signed-off-by: aceppaluni <aceppaluni@gmail.com>
|
Closing as PR has reached over 30 commits. Opening new PR |
Description:
This PR aims to add in the implementation for HIP-1261.
Related issue(s):
Fixes #1633
Notes for reviewer:
Checklist